home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 5 / Apprentice-Release5.iso / Source Code / Libraries / DCLAP 6d / dclap6d / DBio.more / old / USeqDoc.cp < prev    next >
Text File  |  1996-07-05  |  24KB  |  1,005 lines

  1. // USeqDoc.inc.p 
  2.  
  3.     
  4. #pragma segment USeqDoc
  5.  
  6. CONST
  7.     kCodonTableFile == ':Tables:Codon.Table';
  8.     kRenzymeFile == ':Tables:REnzyme.Table';
  9.     kInterleaveTemp == 'seqapp-interleave.temp';
  10.     msgMyError == 0x80001234;
  11.  
  12.  
  13.     
  14. pascal void InitUSequence(void)
  15. {
  16.     gCodonTable[1].amino='?';
  17.     gCodonTable[1].codon='xxx';
  18.     gCodonTable[1].numPerK= 0;
  19.  
  20.     indelHard= '-';
  21.     indelSoft= '~'; //? or '.'
  22.     indelEdge= '.';
  23.  
  24.     /*!!! NEED Internal Codon Table in case default is missing 
  25.         ?? use resource -- stuff one of these into Code/Prefs file ?
  26.         */
  27.     ReadCodonTable(kCodonTableFile); //read default tables...
  28.     
  29.     NEW(gREMap);
  30.     FailNIL(gREMap);
  31.     gREMap->IREMap();
  32.     gREMap->ReadREnzymeTable(kRenzymeFile); 
  33. }
  34.  
  35.  
  36.  
  37.  
  38.  
  39.  
  40.  
  41.  
  42.  
  43.  
  44. // TSeqList  -------------------------------------
  45.  
  46. pascal Boolean TSeqList::ListIsEmpty(void)
  47. VAR  aSeq: TSequence;
  48. {
  49.     if ((this.GetSize > 1))
  50.         ListIsEmpty= FALSE
  51.     else if ((this.GetSize == 1)) {
  52.         aSeq= TSequence(this->First());
  53.         if ((aSeq!=NULL) && (aSeq->fLength > 0))
  54.             ListIsEmpty= FALSE
  55.         else
  56.             ListIsEmpty= TRUE;
  57.         }    else
  58.       ListIsEmpty= TRUE;
  59. }
  60.  
  61. pascal TSequence TSeqList::SeqAt( integer aRow)  
  62. {
  63.     SeqAt= TSequence(this->At( aRow));  
  64. }
  65.  
  66.  
  67. TYPE 
  68.     longarray     == array [0..1] of longint;
  69.     pLongarray    == ^longarray;
  70.     hLongarray     == ^pLongarray;        
  71.  
  72. VAR
  73.     longint        gNoutindex, gOutindexmax;
  74.     hLongarray        gOutindex;
  75.  
  76. pascal void IndexSetup(void)
  77. {
  78.     gNoutindex= 0;
  79.     gOutindexmax= 0;
  80.     gOutindex= hLongarray( NewHandle(0));
  81.     FailNIL( gOutindex);
  82. }
  83.  
  84. pascal void IndexCleanup(void)
  85. {
  86.     gOutindex= hLongarray( DisposeIfHandle( Handle( gOutindex)));
  87. }
  88.  
  89. pascal void IndexOut( longint index)
  90. {
  91.     if (gNoutindex >= gOutindexmax) then begin
  92.         gOutindexmax= gNoutindex + 20; 
  93.         SetHandleSize( Handle(gOutindex), sizeof(longint)*gOutindexmax); 
  94.         FailMemError();
  95.         }
  96.     (*gOutindex)^[gNoutindex]= index;
  97.     gNoutindex= gNoutindex+1;
  98. }
  99.  
  100. pascal void indexEOF( integer fileRef)
  101. VAR index: longint;
  102. {
  103.     // indexout();  noutindex--; /* mark eof */ 
  104.     if (0!=GetFPos( fileRef, index)) then ;
  105.     IndexOut(index);
  106.     gNoutindex= gNoutindex-1;
  107. }
  108.  
  109.  
  110.  
  111. pascal void TSeqList::doWriteRef( integer aFileRef, integer format)  
  112. VAR
  113.         Boolean        needSameSize, sizesDiffer, isInterleaved;
  114.         integer        aRow, nseqs, seqtype, err, vref, fileSave;
  115.         longint        minbases, dirID;
  116.         
  117.     pascal void findMinSize( TSequence aSeq)
  118.     longint        var  start, nbases;
  119.     {
  120.         aSeq->GetSelection( start, nbases);
  121.         seqtype= aSeq->fKind;
  122.         if (minbases<0) then minbases= nbases
  123.         else begin
  124.             if (nbases!=minbases) then sizesDiffer= true;
  125.             minbases= min( nbases, minbases);
  126.             end();
  127.     }
  128.     
  129.     pascal void SetSameSize( TSequence aSeq)
  130.     longint        var  start, nbases;
  131.     {
  132.         aSeq->GetSelection( start, nbases);
  133.         aSeq->SetSelection( start, minbases); 
  134.     }
  135.     
  136.     pascal void writeRangeToFile( TSequence aSeq)
  137.     longint        VAR  index;
  138.     {
  139.         if (isInterleaved) then begin
  140.             if (0!=GetFPos( aFileRef, index)) then;
  141.             IndexOut(index);
  142.             end();
  143.         aSeq->doWriteSelection( aFileRef, format);
  144.     }
  145.     
  146.     FailInfo        VAR  fi;
  147.     pascal void HndlFailure(OSErr error, long message)        
  148.     {
  149.         aFileRef= fileSave;
  150.         IndexCleanup(); 
  151.         if 0!=HDelete(vRef, dirID, kInterleaveTemp) then ;
  152.     }
  153.     
  154.     
  155. {    
  156.     fileSave= aFileRef;
  157.     gOutindex= NULL; //make sure for failure
  158.     vref= gAppVolRef; dirID= gAppDirID; 
  159.     needSameSize= false;
  160.     isInterleaved= false;
  161.     sizesDiffer= false;
  162.     seqtype= kOtherSeq;
  163.     minbases= -1; 
  164.     nseqs= this->GetSize();
  165.     
  166.     if (nseqs>1)) // deal w/ one-per-file formats 
  167.         switch (format) {
  168.             kGCG        : format= kMSF;
  169.             kStrider: format= kIG;
  170.             kNoformat, kPlain, kUnknown: format= kGenbank;
  171.             }
  172.         
  173.     this->Each( findMinSize);    
  174.     
  175.     WriteSeqHeader(aFileRef, FALSE, format, nseqs, minbases, gOutputName, 
  176.                 needSameSize, isInterleaved);
  177.  
  178.     CatchFailures(fi, HndlFailure);
  179.     if (isInterleaved) {
  180.         IndexSetup();
  181.         err= FindFolder(kOnSystemDisk,kTemporaryFolderType,kCreateFolder,vRef,dirID);
  182.         if (err!=0)) { vref= gAppVolRef; dirID= gAppDirID; }
  183.         if 0!=HDelete(vRef, dirID, kInterleaveTemp) then ;
  184.         FailOSErr( HCreate( vRef, dirID, kInterleaveTemp, kSappSig, 'TEXT'));
  185.         FailOSErr( HOpen( vRef, dirID, kInterleaveTemp, fsRdWrPerm, aFileRef));
  186.         }
  187.     
  188.     if (((needSameSize || isInterleaved/*?*/) && sizesDiffer)) {
  189.         /*---
  190.         ParamText('all sequences must have same # bases for this format','', 'WriteSeq','');    
  191.         Failure( -1, msgMyError); 
  192.         ---*/
  193.         this->Each( SetSameSize);
  194.         }
  195.  
  196.     this->Each( writeRangeToFile);        
  197.     
  198.         /* ^^ if format in [interleaved kinds] then 
  199.             (a) write header info to aFileRef
  200.             (b) open temp file, write sequential seqs to that
  201.             (c) rewind temp, interleave and write to aFileRef
  202.             (d) write trailer info
  203.             -- make writeHeader, writeTrailer methods of TSeqList...
  204.             ** need alert dlogs for (1) oneperfile, (2) needSameSize problems
  205.         */
  206.  
  207.     if (isInterleaved) {
  208.         indexEOF( aFileRef);
  209.         DoInterleave( fileSave, FALSE/*isHandle*/, format, seqtype, nseqs,
  210.                                     minbases, gLinesPerSeqWritten, 
  211.                                     gNoutindex, Handle(gOutindex), aFileRef);
  212.  
  213.         FailOSErr( FSClose(aFileRef));
  214.         if 0!=HDelete(vRef, dirID, kInterleaveTemp) then ;
  215.         IndexCleanup();
  216.         }
  217.     aFileRef= fileSave;
  218.     Success(fi);
  219.         
  220.     WriteSeqTrailer( aFileRef, FALSE, format, this->GetSize(), gLinesPerSeqWritten, minbases);
  221.  
  222. }
  223.  
  224.  
  225. pascal void TSeqList::doWrite( Str255 aFileName, integer format)  
  226. VAR  err, aFileRef: integer;
  227. {
  228.     gOutputName= aFileName;
  229.     err= FSDelete( aFileName, 0);  //!?? must check before call if overwrite is okay ????
  230.     FailOSErr( Create( aFileName, 0, kSAppSig, 'TEXT'));
  231.     FailOSErr( FSOpen( aFileName, 0, aFileRef));
  232.     
  233.     doWriteRef( aFileRef, format);
  234.     
  235.     FailOSErr( FSClose( aFileRef));
  236. }
  237.  
  238.  
  239. pascal Handle TSeqList::doWriteHandle( integer format)  
  240. VAR
  241.         Handle        aHand, handSave;
  242.         Boolean        needSameSize, sizesDiffer, isInterleaved;
  243.         integer        aRow, nseqs, seqtype, err, vref, tempFileRef;
  244.         longint        minbases, dirID;
  245.         
  246.     pascal void findMinSize( TSequence aSeq)
  247.     longint        var  start, nbases;
  248.     {
  249.         aSeq->GetSelection( start, nbases);
  250.         seqtype= aSeq->fKind;
  251.         if (minbases<0) then minbases= nbases
  252.         else {
  253.             if (nbases!=minbases) then sizesDiffer= true;
  254.             minbases= min( nbases, minbases);
  255.             }
  256.     }
  257.     
  258.     pascal void SetSameSize( TSequence aSeq)
  259.     longint        var  start, nbases;
  260.     {
  261.         aSeq->GetSelection( start, nbases);
  262.         aSeq->SetSelection( start, minbases);
  263.     }
  264.     
  265.     pascal void writeRangeToHand( TSequence aSeq)
  266.     longint        VAR index;
  267.     {
  268.         if (isInterleaved) then begin
  269.             if (0!=GetFPos( tempFileRef, index)) then ;
  270.             IndexOut(index);
  271.             aSeq->doWriteSelection( tempFileRef, format);
  272.             end
  273.         else
  274.             aSeq->doWriteSelectionHandle( aHand, format);
  275.     }
  276.         
  277.     FailInfo        VAR  fi;
  278.     pascal void HndlFailure(OSErr error, long message)        
  279.     {
  280.         IndexCleanup(); 
  281.         aHand= DisposeIfHandle( aHand);
  282.     }
  283.     
  284.     
  285. {
  286.     gOutindex= NULL; //make sure for failure
  287.     aHand= NULL;
  288.     minbases= -1; 
  289.     needSameSize= false;
  290.     isInterleaved= false;
  291.     sizesDiffer= false;
  292.     seqtype= kOtherSeq;
  293.     nseqs= this->GetSize();
  294.     this->Each( findMinSize);        
  295.  
  296.     if (nseqs>1)) // deal w/ one-per-file formats 
  297.         switch (format) {
  298.             kGCG        : format= kMSF;
  299.             kStrider: format= kIG;
  300.             kNoformat, kPlain, kUnknown: format= kGenbank;
  301.             }
  302.  
  303.     CatchFailures(fi, HndlFailure);
  304.     aHand= NewPermHandle(0);
  305.     FailMemError();
  306.     
  307.     WriteSeqHeader(longint(aHand), TRUE, format, nseqs, minbases, gOutputName,
  308.             needSameSize, isInterleaved);
  309.             
  310.     if (isInterleaved) {
  311.         IndexSetup();
  312.         err= FindFolder(kOnSystemDisk,kTemporaryFolderType,kCreateFolder,vRef,dirID);
  313.         if (err!=0)) { vref= gAppVolRef; dirID= gAppDirID; }
  314.         if 0!=HDelete(vRef, dirID, kInterleaveTemp) then ;
  315.         FailOSErr( HCreate( vRef, dirID, kInterleaveTemp, kSappSig, 'TEXT'));
  316.         FailOSErr( HOpen( vRef, dirID, kInterleaveTemp, fsRdWrPerm, tempFileRef));
  317.         }
  318.     
  319.     if (((needSameSize || isInterleaved/*?*/) && sizesDiffer)) {
  320.         /*---
  321.         ParamText('all sequences must have same # bases for this format', '', 'WriteSeq','');    
  322.         Failure( -1, msgMyError); 
  323.         ---*/
  324.         this->Each( SetSameSize);
  325.         }
  326.  
  327.     this->Each( writeRangeToHand);        
  328.  
  329.     if (isInterleaved) {
  330.         indexEOF( tempFileRef);
  331.         DoInterleave( longint(aHand), TRUE/*isHandle*/, format, seqtype, nseqs,
  332.                                     minbases, gLinesPerSeqWritten, 
  333.                                     gNoutindex, Handle(gOutindex), tempFileRef);
  334.  
  335.         FailOSErr( FSClose(tempFileRef));
  336.         if 0!=HDelete(vRef, dirID, kInterleaveTemp) then ;
  337.         IndexCleanup();
  338.         }
  339.  
  340.     WriteSeqTrailer(longint(aHand), TRUE, format, this->GetSize(), gLinesPerSeqWritten, minbases);
  341.  
  342.     Success(fi);    
  343.     doWriteHandle= aHand;
  344. }
  345.  
  346.  
  347. pascal void TSeqList::AddNewSeq(void)
  348. VAR  aSeq: TSequence;
  349. {
  350.     NEW(aSeq); 
  351.     FailNIL(aSeq);
  352.     aSeq->ISequence(); 
  353.     InsertLast( aSeq);
  354.     aSeq->fIndex= this->GetSize();
  355. }
  356.  
  357. pascal void TSeqList::ClearSelections(void)
  358.     pascal void clearOne( TSequence aSeq)
  359.     {
  360.         aSeq->ClearSelection();
  361.     }
  362. {
  363.     this->Each(ClearOne);
  364. }
  365.  
  366. pascal integer TSeqList::ZeroOrigin(void)
  367. VAR    shiftall: integer;
  368.  
  369.     pascal void findshift( TSequence aSeq)
  370.     {
  371.         if ((aSeq->fOrigin<0))
  372.             shiftall= min(shiftall, aSeq->fOrigin);
  373.     }
  374.     
  375.     pascal void doshift( TSequence aSeq)
  376.     {
  377.         aSeq->fOrigin= aSeq->fOrigin - shiftall;
  378.         if (aSeq->fOrigin > 0) {
  379.             aSeq->InsertSpacers( 0, aSeq->fOrigin, indelEdge);
  380.             aSeq->fOrigin= 0;
  381.             }
  382.     }
  383. {
  384.     shiftall= 0;
  385.     this->Each(findshift);
  386.     this->Each(doshift);
  387.     ZeroOrigin= shiftall;
  388. }
  389.  
  390.  
  391. pascal TSequence TSeqList::Consensus(void)
  392. VAR     cons: TSequence;
  393.     pascal boolean isConsensus( TSequence aSeq)
  394.     {
  395.         isConsensus= aSeq.isConsensus;
  396.     }
  397. {
  398.     Consensus= TSequence(this->FirstThat(isConsensus));         
  399. }
  400.  
  401.  
  402. pascal Integer TSeqList::ConsensusRow(void)
  403. VAR     cons: TSequence;
  404. {
  405.     cons= this->Consensus();        
  406.     if ((cons != NULL)) 
  407.         ConsensusRow= this->GetIdentityItemNo( cons) 
  408.     else
  409.         ConsensusRow= 0;
  410. }
  411.  
  412. pascal void TSeqList::MakeConsensus(void)
  413. VAR  
  414.     TSequence        cons;
  415.     CharsHandle        hCon, hSeq;
  416.     integer        count ;
  417.     len, conlen        : longint;
  418.     arow    : integer;
  419.     arect    : VRect;
  420.     
  421.     pascal void addToCons(TSequence aSeq)
  422.     VAR         i : integer;
  423.     {
  424.         if (!(aSeq.isConsensus || (aSeq->fKind=kOtherSeq))) {
  425.             count= count+1;
  426.             handle(hSeq)= aSeq->fBases;
  427.             len= GetHandleSize(Handle(hSeq));
  428.             if (len > conlen then begin
  429.                 conlen= len;
  430.                 SetHandleSize( Handle(hCon), conlen);
  431.                 FailMemError();
  432.                 }
  433.             if (count=1) {
  434.                 for i= 0 to len-1 do (*hCon)^[i]= (*hSeq)^[i];
  435.                 }            else {
  436.                 for i= 0 to len-1 do  
  437.                     (*hCon)^[i]= NucleicConsensus(NucleicBits((*hCon)^[i]), NucleicBits((*hSeq)^[i]));  
  438.                 }
  439.             }
  440.     }
  441.         
  442. {
  443.     cons= this->Consensus();        
  444.     if ((cons=NULL)) {
  445.         NEW(cons); 
  446.         FailNIL(cons);
  447.         cons->ISequence();
  448.         cons->fName= kConsensus;
  449.         InsertLast( cons); //?? first or last 
  450.         cons->fIndex= this->GetSize();
  451.         }
  452.         
  453.     if ((cons != NULL)) {
  454.         arow= this->GetIdentityItemNo( cons);
  455.         handle(hCon)= cons->fBases;   
  456.         conlen= GetHandleSize(handle(hCon));
  457.         count= 0;
  458.         this->Each( addToCons);  
  459.         }
  460. }
  461.  
  462.  
  463. pascal charsHandle TSeqList::FindCommonBases( integer minCommonPerCent, 
  464.                                             CharsHandle VAR firstCommon)
  465. VAR  
  466.     TSequence        cons;
  467.     CharsHandle        hCon, hSeq;
  468.     longint        len, maxlen, conlen, ibase;
  469.     arow    : integer;
  470.     letcount : array ['A'..'Z'] of integer;
  471.     letfirst : array ['A'..'Z'] of byte;
  472.     integer        spccount, nilcount ;
  473.  
  474.     integer        nseq ;
  475.     maxc    : real;
  476.     char        maxch, ch;
  477.     CharsHandle        hMaxbase;
  478.     hAtbase    : CharsHandle;
  479.     
  480.     pascal void findCommon(TSequence aSeq)
  481.     char        VAR ch;
  482.     {
  483.         if !(aSeq.isConsensus || (aSeq->fKind=kOtherSeq)) then {
  484.             nseq= nseq+1;
  485.             handle(hSeq)= aSeq->fBases;
  486.             len= GetHandleSize(Handle(hSeq));
  487.             /*------
  488.             maxlen= max(maxlen, len);
  489.             -------*/
  490.             ch= toupper( (*hSeq)^[ibase]);
  491.             if (ch >= 'A') && (ch <= 'Z') then begin
  492.                 letcount[ch]= letcount[ch]+1;
  493.                 if (letfirst[ch] < 1) then letfirst[ch]= Min(255, nseq);
  494.                 end
  495.             else if (ch == indelSoft) || (ch == indelHard) || (ch == indelEdge)
  496.                 || (ch == ' ') || (ch == '_') then
  497.                 spccount= spccount+1
  498.             else 
  499.                 nilcount= nilcount+1;
  500.             }
  501.     }
  502.         
  503. {
  504.     cons= this->Consensus();        
  505.     if ((cons=NULL)) cons= TSequence(this->First()); //any seq will do...
  506.     
  507.     hMaxBase= NULL;
  508.     firstCommon= NULL;
  509.     if ((cons!=NULL)) {        
  510.         arow= this->GetIdentityItemNo( cons);
  511.         handle(hCon)= cons->fBases;   
  512.         maxlen= GetHandleSize(handle(hCon)); //???
  513.         
  514.         handle(hMaxBase)= NewHandle(maxlen); 
  515.         FailMemError();
  516.         handle(firstCommon)= NewHandle(maxlen); 
  517.         FailMemError();
  518.         
  519.         FOR ibase= 0 to maxlen-1/*?*/ do {
  520.             for ch= 'A' to 'Z' do begin letcount[ch]= 0; letfirst[ch]= 0; end;
  521.             nilcount= 0; 
  522.             spccount= 0;
  523.             nseq= 0;
  524.             this->Each( findCommon);
  525.             maxc= 0;
  526.             FOR ch= 'A' to 'Z' do 
  527.                 if letcount[ch] > maxc then { 
  528.                     maxc= letcount[ch]; 
  529.                     maxch= ch; 
  530.                     }
  531.             if ((100 * maxc / nseq) >= minCommonPerCent) then  //mark maxch's
  532.                 (*hMaxbase)^[ibase]= maxch
  533.             else
  534.                 (*hMaxbase)^[ibase]= '!';
  535.             (*firstCommon)^[ibase]= ((char)(letfirst[maxch]));
  536.             }
  537.         }
  538.     
  539.     FindCommonBases= hMaxBase;
  540. }
  541.  
  542.  
  543.  
  544.  
  545.  
  546.  
  547.  
  548. // TSeqListView            == OBJECT (TTextListView) ------------------
  549.  
  550.  
  551. pascal void TSeqListView::Infoheadline(Str255 var aStr)
  552. var  
  553.     str255        s ;
  554. {
  555.     s= 'Sequence';
  556.     while length(s) < kMaxSname do s= concat(s,' ');
  557.     aStr= s;
  558.     s= 'Kind   ';  
  559.     aStr= concat(aStr,' ',s);
  560.     s='  Size';
  561.     aStr= concat(aStr,' ',s);
  562.     s=' Check';
  563.     astr= concat(astr,'  ',s);
  564.     s= 'Bases';
  565.     while length(s) < kMaxSeqShow do s= concat(s,' ');
  566.     astr= concat(astr,' ',s);
  567.     s='Last Modified';
  568.     astr= concat(astr,' ',s);
  569. }
  570.  
  571. pascal void TSeqListView::GetItemText(integer anItem, Str255 VAR aString)
  572.             // override 
  573. VAR
  574.         TSequence        aSeq;
  575. {
  576.     aString= '-';
  577.   if fSeqList != NULL then 
  578.      if (anItem <= fSeqList->fSize) then begin
  579.         aSeq= TSequence(fSeqList->At(anItem));
  580.         if aSeq != NULL then aSeq->Infoline(aString);
  581.         end();
  582. }
  583.  
  584.  
  585. pascal void TSeqListView::Initialize(void) // override 
  586. {
  587.     inherited::Initialize();
  588.     fSeqList= NULL; 
  589. }
  590.  
  591.  
  592. pascal void TSeqSelectCommand::ComputeNewSelection(GridCell VAR clickedCell) // override 
  593. {
  594.     //keep selection fixed at max size ?
  595.   if fShiftKey 
  596.         && !fGridView->fSingleSelection 
  597.         && fGridView->IsCellSelected(clickedCell))  
  598.           clickedCell= fGridView->LastSelectedCell(); //last line
  599.  
  600.     inherited::ComputeNewSelection(clickedCell);
  601. }
  602.  
  603.  
  604. pascal void TSeqSelectCommand::DoIt(void) // override 
  605. //example/dummy DoIt
  606. var
  607.     aCell    : GridCell;
  608. {
  609.     inherited::DoIt();
  610.     aCell.h= 1;
  611.     aCell.v= fAtRow;
  612.     if !fGridView->IsCellSelected( aCell) then fDoubleClick= FALSE;
  613.     
  614.     if fDoubleClick then TSeqListDoc(fView->fDocument).DoSeqSelectCommand;
  615. }
  616.  
  617.  
  618. /*--
  619. pascal TCommand TSeqListView::DoMouseCommand(VAR theMouse:Point; EventInfo VAR Info,
  620.             point VAR hysteresis) // override 
  621. --*/
  622. pascal void TSeqListView::DoMouseCommand(VPoint VAR theMouse, TToolboxEvent event,
  623.                                                Point hysteresis) // override 
  624. VAR
  625.     aCell    : GridCell;
  626.     aCommand        : TSeqSelectCommand;
  627.     boolean        doToggle, doShift;
  628. {
  629.     if ((IdentifyPoint(theMouse, aCell) != badChoice)) {
  630.         New(aCommand);
  631.         FailNIL(aCommand);
  632.         aCommand->fDoubleClick= (event->fClickCount > 1);
  633.         aCommand->fAtRow= aCell.h;
  634.         if (firstSelectedItem <= aCell.h) && (lastSelectedItem >= aCell.h) then
  635.             doShift= TRUE
  636.         else
  637.             doShift= event->IsShiftKeyPressed(); //- info.theShiftKey;
  638.         if aCommand->fDoubleClick then
  639.             doToggle= FALSE
  640.         else if (firstSelectedItem == aCell.h) && (lastSelectedItem == aCell.h) then
  641.             doToggle= TRUE
  642.         else 
  643.             doToggle= event->IsCommandKeyPressed(); //-info.theCommandKey;
  644.         aCommand->ICellSelectCommand(this, theMouse, doShift, doToggle);
  645.         PostCommand( aCommand);
  646.         }
  647. }
  648.  
  649.  
  650.  
  651. /*-- pascal TCommand TSeqListDlog::DoMouseCommand(VAR theMouse:Point; EventInfo VAR Info,
  652.                             point VAR hysteresis) // override */ ---
  653. pascal void TSeqListDlog::DoMouseCommand(VPoint VAR theMouse, TToolboxEvent event,
  654.                                                Point hysteresis) // override 
  655. {
  656.     TSeqListDoc(fDocument).fSeqListView->SetEmptySelection(kHighlight);
  657.     inherited::DoMouseCommand( theMouse, event, hysteresis);
  658. }
  659.  
  660. pascal void TSeqListDlog::CalcMinFrame(VRect VAR minFrame) // override 
  661. //! need to check CalcMinFrame of window 
  662. var  aDoc: TSeqListDoc;
  663.          longint        dsize;
  664.          VRect        listVRect;
  665. {
  666.   inherited::CalcMinFrame(minFrame); //do horiz ?
  667.     
  668.     aDoc= TSeqListDoc(fDocument);
  669.     dsize= 0;
  670.     if ((aDoc->fSeqList != NULL)) 
  671.         dsize= aDoc->fSeqList.fSize + 2;
  672.     /*-- 
  673.         fSeqListView is NULL now when called from NewTemplateWindow 
  674.         at top of TSeqListDoc.DoMakeViews
  675.         ... adding TSeqListDlog.IRes w/ inits may overcome that
  676.     ---*/
  677.     
  678.     if ((aDoc->fSeqListView != NULL)) {
  679.         aDoc->fSeqListView->GetFrame( listVRect);
  680.         dsize= listVRect.top + (aDoc->fSeqListView.fLineHeight * dsize);
  681.         }
  682.     minFrame.bottom= max(minFrame.bottom, dsize);
  683. }
  684.  
  685.  
  686. pascal void TSeqListDlog::Initialize(void) // override 
  687. {
  688.     inherited::Initialize();
  689. }
  690.  
  691.  
  692.  
  693. // TSeqListDoc     ----------
  694.  
  695. CONST
  696.         kProjType == 'TEXT';
  697.         kSeqListDocID == 1007;
  698.         
  699. pascal void unDeadStripObjects(void)
  700. {
  701.     if (gDeadStripSuppression) {
  702.     /*---
  703.         if (Member(TObject(NULL), TReadGCG));
  704.         if (Member(TObject(NULL), TReadFitch));
  705.         if (Member(TObject(NULL), TReadZuker));
  706.         if (Member(TObject(NULL), TReadEMBL));
  707.         if (Member(TObject(NULL), TReadPearson));
  708.         if (Member(TObject(NULL), TReadNBRF));
  709.         if (Member(TObject(NULL), TReadGB));
  710.         if (Member(TObject(NULL), TReadStrider));
  711.         if (Member(TObject(NULL), TReadIG));
  712.         if (Member(TObject(NULL), TReadSeq));
  713.         if (Member(TObject(NULL), TReadOlsen));
  714.     ----*/        
  715.         if (Member(TObject(NULL), TSequence));
  716.         if (Member(TObject(NULL), TSeqList));
  717.         if (Member(TObject(NULL), TSeqListView));
  718.         if (Member(TObject(NULL), TSeqListDlog));
  719.         if (Member(TObject(NULL), TSeqListDoc));
  720.         }
  721. }
  722.  
  723.  
  724.  
  725. pascal void TSeqListDoc::ISeqListDoc(TFile itsFile)
  726. VAR
  727.     aSeq        : TSequence;
  728. {
  729.     UnDeadStripObjects(); //!? keep'em in code
  730.     
  731.     this->IFileBasedDocument(itsFile, kProjType);
  732.     
  733.     fInFormat= kNoformat;
  734.     fHeadline    = NULL;
  735.     fUpdateTime= 0;
  736.     fSeqListView= NULL;
  737.     gSeqListDoc= this; //!*/    /*? store other gSeqListDocs in gApp.TList ?
  738.     GetTitle(gDefSeqName);
  739.     fSaveSelection= false;    
  740.  
  741.     //! do this in .ISeqListDoc, as DoRead comes before DoMakeViews 
  742.     fSeqList= TSeqList(NewList);  
  743.     FailNIL(fSeqList);
  744.     fSeqList->AddNewSeq();    // install 1 blank seq for new doc
  745. }
  746.  
  747.  
  748.  
  749. pascal Boolean TSeqListDoc::ListIsEmpty(void)
  750. {
  751.     if ((fSeqList!=NULL)) ListIsEmpty= fSeqList.ListIsEmpty
  752.     else ListIsEmpty= TRUE;
  753. }
  754.  
  755.  
  756. pascal void TSeqListDoc::AddSeqToList(TSequence item)
  757. var last: integer;
  758. {
  759.     fSeqList->InsertLast(item);
  760.     item->fIndex= fSeqList->GetSize();
  761.     if (fSeqListView!=NULL) {
  762.         fSeqListView->InsItemLast(1);
  763.         last= fSeqListView->fNumOfRows;
  764.         fSeqListView->SelectItem( last, FALSE, TRUE, TRUE);
  765.         }
  766.     //- fChangeCount= fChangeCount+1;
  767.     this->Changed( 1, this);
  768. }    
  769.  
  770. pascal void TSeqListDoc::AddNewSeqToList(void)
  771. VAR  aSeq: TSequence;
  772. {
  773.     NEW(aSeq); 
  774.     FailNIL(aSeq);
  775.     aSeq->ISequence(); 
  776.     AddSeqToList( aSeq);
  777. }
  778.  
  779.  
  780. pascal void TSeqListDoc::DoSeqSelectCommand(void)
  781. {
  782.     //OVERRIDE this to do something w/ selected seqs on dblclk
  783. }
  784.  
  785.  
  786. pascal void TSeqListDoc::DoMakeViews(Boolean forPrinting) // override 
  787. VAR
  788.         s        : str255;
  789.         TView        aView;
  790.         TSeqListDlog        aDialogView;
  791.         TStdPrintHandler        aHandler;
  792. {
  793.     fHeadline= NULL;
  794.     fSeqListView= NULL;
  795.     aView = gViewServer->NewTemplateWindow(kSeqListDocID, this);
  796.     FailNIL(aView);                  
  797.      
  798.   fHeadline = TStaticText(aView->FindSubView('HEAD'));
  799.     FailNIL(fHeadline);
  800.     fSeqListView= TSeqListView(aView->FindSubView('LIST'));
  801.     FailNIL(fSeqListView);
  802.   fFormatPop= TPopup(aView->FindSubView('pFMT'));
  803.  
  804.     fSeqListView->fSeqList= fSeqList;  
  805.     fSeqListView->Infoheadline(s);    
  806.     fHeadline->SetText( s, FALSE);
  807.     
  808.     //get superview of window, minus scrolls, for printing
  809.     aDialogView = TSeqListDlog(aView->FindSubView('DLOG'));       
  810.     New(aHandler);
  811.     FailNIL(aHandler);
  812.     aHandler->IStdPrintHandler(this,                     // its document 
  813.                               aDialogView,                    // its view 
  814.                               !kSquareDots,            // does not have square dots 
  815.                               kFixedSize,                 // horzontal page size is fixed 
  816.                               !kFixedSize);            /* vertical page size is variable (could be
  817.                                                           set to TRUE on non-style TE systems) */
  818.  
  819.     ShowReverted();
  820. }
  821.  
  822.  
  823.  
  824. pascal void TSeqListDoc::DoSetupMenus(void) // override 
  825. {
  826.   inherited::DoSetupMenus();    
  827. }
  828.  
  829. pascal void TSeqListDoc::DoMenuCommand(CommandNumber aCommandNumber) // override 
  830. {
  831.     inherited::DoMenuCommand(aCommandNumber);
  832. }
  833.  
  834.  
  835.  
  836. pascal void TSeqListDoc::ShowReverted(void) // override 
  837. var  nnew, nold: integer;
  838.          longint        t;
  839.          
  840.         procedure update(TSequence aSeq)
  841.         begin
  842.          //?? can't do "<" comparison of times, negative longint
  843.          //- if fUpdateTime < aSeq->fModTime then  
  844.          if aSeq->fChanged then aSeq->UpdateFlds();
  845.         end();
  846.         
  847. {
  848.     inherited::ShowReverted();
  849.     
  850.     fSeqList->each(update);
  851.     if ((fSeqListView!=NULL)) {
  852.         fSeqListView->fSeqList= fSeqList;  
  853.         nold= fSeqListView->fNumOfRows;
  854.         nnew= fSeqList->fSize;
  855.         fSeqListView->DelItemLast(nold);
  856.         fSeqListView->InsItemLast(nnew);
  857.         }
  858.     GetDateTime(t);
  859.     fUpdateTime    = t;
  860. }
  861.  
  862.  
  863.  
  864. /***
  865. function TSeqListDoc.filedate: longint;
  866. begin
  867.     HLock(Handle(fTitle));
  868.     //$Push*/ /*$H-
  869.     filedate = FileModDate((*fTitle)^, fVolRefNum);
  870.     //$Pop
  871.     HUnLock(Handle(fTitle));
  872. end;
  873. ****/
  874.  
  875.  
  876.  
  877.  
  878. pascal void TSeqListDoc::AppendRead(short aRefNum)
  879. {    
  880.     GetTitle(gDefSeqName);
  881.     fInFormat= ReadSeqFile(aRefNum, FALSE, fSeqList);  
  882. }
  883.  
  884. pascal void TSeqListDoc::AppendHandle( Handle aHand)
  885. {    
  886.     GetTitle(gDefSeqName);
  887.     fInFormat= ReadSeqFile(Longint(aHand), TRUE, fSeqList);  
  888. }
  889.  
  890.  
  891.  
  892. pascal void TSeqListDoc::AboutToSaveFile(TFile theSaveFile, CommandNumber itsCmd, 
  893.                                                             Boolean VAR makingCopy) // override 
  894. VAR
  895.         Boolean        needSameSize, sizesDiffer, isInterleaved;
  896.         integer        nseqs, err, format ;
  897.         longint        minbases;
  898.         Handle        aHand;
  899.         
  900.     pascal void checkEqualSize( TSequence aSeq)
  901.     longint        var  start, nbases;
  902.     {
  903.         //aSeq->GetSelection( start, nbases); << can still be set from fSelection or other old selecting command 
  904.         nBases= aSeq->fLength; 
  905.         if (minbases<0) then minbases= nbases
  906.         else begin
  907.             if (nbases!=minbases) then sizesDiffer= true;
  908.             //- minbases= min( nbases, minbases); 
  909.             end();
  910.     }
  911.  
  912. {
  913.     inherited::AboutToSaveFile(theSaveFile, itsCmd, makingCopy);
  914.     
  915.     if ((!fSaveSelection)) { 
  916.                     //^^^^ !???? TAlnDoc will set this, always equal #bases????
  917.         if (fFormatPop == NULL) format= kGenBank
  918.         else format= fFormatPop->GetCurrentItem(); 
  919.         needSameSize= false;
  920.         isInterleaved= false;
  921.         sizesDiffer= false;
  922.         minbases= -1; 
  923.         nseqs= fSeqList->GetSize();
  924.         
  925.         if (nseqs>1)) // deal w/ one-per-file formats 
  926.             switch (format) {
  927.                 kGCG        : format= kMSF;
  928.                 kStrider: format= kIG;
  929.                 kNoformat, kPlain, kUnknown: format= kGenbank;
  930.                 }
  931.             
  932.         fSeqList->ClearSelections(); //! make sure we write all of seq from this call !?
  933.         fSeqList->Each( checkEqualSize);    
  934.     
  935.         aHand= NewHandle(0);
  936.         WriteSeqHeader( longint(aHand), TRUE, format, nseqs, minbases, gOutputName, 
  937.                     needSameSize, isInterleaved); //<< need write for last two results 
  938.         aHand= DisposeIfHandle(aHand);
  939.         
  940.         if (((needSameSize || isInterleaved/*?*/) && sizesDiffer)) {
  941.             ParamText('all sequences must have same # bases for this format',
  942.                     ' Pick another format like Genbank or change selection.',
  943.                     'WriteSeq','');    
  944.             Failure( -1, msgMyError);  
  945.             }
  946.         }
  947. }
  948.  
  949.  
  950. pascal void TSeqListDoc::DoRead(TFile aFile, Boolean forPrinting) // override 
  951. {
  952.     //? if forPrinting then ???
  953.     FreeData();   //free initial stuff
  954.   AppendRead( aFile->fDataRefNum); //<< change AppendRead to use aFile.WriteData ?
  955. }
  956.  
  957. pascal void TSeqListDoc::DoReadHandle(Handle aHand)
  958. {
  959.     FreeData();   //free initial stuff
  960.   AppendHandle( aHand);
  961. }
  962.  
  963.  
  964.     
  965. pascal void TSeqListDoc::DoWrite(TFile aFile, Boolean makingCopy) // override 
  966. VAR   outformat: integer;  Str63 aStr63,
  967. {
  968.     aFile->GetName( aStr63); gOutputName= aStr63;
  969.     if (fFormatPop == NULL) outformat= kGenBank
  970.     else outformat= fFormatPop->GetCurrentItem(); 
  971.     fSeqList->ClearSelections(); //! make sure we write all of seq from this call !?
  972.     fSeqList->doWriteRef( aFile->fDataRefNum, outformat);
  973. }
  974.  
  975.  
  976. pascal void TSeqListDoc::Close(void) // override 
  977. //must make sure all windows owned by ListDoc are closed 1st
  978.  
  979.     procedure closeSubwindows(TWindow aWind)
  980.     begin
  981.       // this is a subwindow !may not be owned by this  doc
  982.         if (!aWind->fClosesDocument) aWind->CloseAndFree();
  983.     end();
  984.     
  985. {
  986.     ForAllWindowsDo(closeSubwindows);
  987.     inherited::Close();
  988. }
  989.  
  990. pascal void TSeqListDoc::Free(void) // override 
  991. {
  992.     FreeData();
  993.     TSortedList(fSeqList)= FreeListIfObject( fSeqList);
  994.     if (fSeqListView!=NULL) fSeqListView->fSeqList= NULL;
  995.     gSeqListDoc= NULL;
  996.     inherited::Free();
  997. }
  998.  
  999. pascal void TSeqListDoc::FreeData(void) // override 
  1000. {
  1001.     if (fSeqList != NULL) fSeqList->FreeAll(); //frees each item, sets fsize=0
  1002. }
  1003.  
  1004.  
  1005.